#ifndef PCB_H
#define PCB_H

#include "types.h"
#include "registers.h"
#include "message_queue.h"

/* type declarations */

/* states definition */
#define READY_STATE 0
#define RUNNING_STATE 1
#define BLOCKED_STATE 2
#define DELAYED_STATE 3
#define WAITING_IO_UART_STATE 4
#define DOING_IO_UART_STATE 5
#define WAITING_CHILD_TERM_STATE 6
#define ZOMBIE_STATE 7

#define MAX_SUPERVISION 20

struct _pcb;

typedef struct{
  struct _pcb* pcb[MAX_SUPERVISION];
  int count;
}supervision_queue;

/* PCB definition */
typedef struct _pcb{
  registers_t registers;
  uint8_t in_use;
  int32_t priority;
  int32_t pid;
  int32_t parent;
  uint32_t state;
  int32_t program_id;
  int32_t waiting_for; //store the pid the process is waiting for during a call to wait
  int32_t status; //store the return value when the process terminates
  uint32_t delay;
  message_queue m_queue; 
  supervision_queue supervisors;
  supervision_queue supervised;
}PCB;

/* function declarations */

/* setters */
void pcb_set_priority(PCB* target, int32_t priority);

void pcb_set_pid(PCB* target, int32_t pid);

void pcb_set_in_use(PCB* target, uint8_t in_use);

void pcb_set_epc(PCB* target, uint32_t pc);

void pcb_set_state(PCB* target, uint32_t state);

void pcb_set_sp(PCB* target, uint32_t address);

void pcb_set_delay(PCB* target, uint32_t delay);

void pcb_set_program_id(PCB* target, int32_t program_id);

void pcb_set_parent(PCB* target, int32_t parent); 

void pcb_set_waiting_for(PCB* target, int32_t pid);

void pcb_set_status(PCB* target, int32_t status);

/* getters */
int32_t pcb_get_pid(PCB* target);

int32_t pcb_get_priority(PCB* target);

uint32_t pcb_get_state(PCB* target);

uint8_t pcb_get_in_use(PCB* target);

uint32_t pcb_get_delay(PCB* target);

uint32_t pcb_get_epc(PCB* target);

/* returns a pointer to the registers field of a PCB */
registers_t* pcb_get_registers(PCB* target);

int32_t pcb_get_program_id(PCB* target);

/* returns a pointer to the message queue of the PCB */
message_queue* pcb_get_message_queue(PCB* target);

int32_t pcb_get_parent(PCB* target);

int32_t pcb_get_waiting_for(PCB* target);

int32_t pcb_get_status(PCB* target);

supervision_queue* pcb_get_supervisors(PCB* target);

supervision_queue* pcb_get_supervised(PCB* target);

#endif


